package aliyun

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/emersion/go-webdav"
	"github.com/gylang/aliyun/webdav/aliyun/model/req"
	"github.com/gylang/aliyun/webdav/aliyun/model/res"
	"github.com/gylang/aliyun/webdav/conf"
	"github.com/gylang/aliyun/webdav/model"
	"github.com/prometheus/common/log"
	"io"
	log2 "log"
	"net/http"
	"path"
	"path/filepath"
	"strings"
)

type AliFileSystem string

func (a AliFileSystem) Open(name string) (io.ReadCloser, error) {

	file := GetFileFromFileCache(name)
	if file != nil {
		m := map[string]string{"drive_id": conf.AliConfSet.DriveId, "file_id": file.FileId}
		bs, err := DoPost(FileDownloadUrl, m)
		if err != nil {
			return nil, err
		}
		reader := bytes.NewReader(bs)
		return io.NopCloser(reader), nil
	}
	return nil, fmt.Errorf("文件/文件夹不存在")
}

func (a AliFileSystem) Stat(name string) (*webdav.FileInfo, error) {
	p, err := a.localPath(name)
	if err != nil {
		return nil, err
	}
	if "/" == p {

		// 请求获取主文件夹
		rootReq := req.FileList{
			All:                   true,
			DriveId:               conf.AliConfSet.DriveId,
			ImageThumbnailProcess: "image/resize,w_400/format,jpeg",
			ImageUrlProcess:       "image/resize,w_1920/format,jpeg",
			Fields:                "*",
			VideoThumbnailProcess: "video/snapshot,t_0,f_jpg,ar_auto,w_300",
			ParentFileId:          "root",
			UrlExpireSec:          1600,
		}
		rootByte, err := DoPost(FileList, rootReq)
		if err != nil {
			return nil, &model.HTTPError{Code: http.StatusNotFound, Err: err}
		}
		var root []*res.TFile
		err = json.Unmarshal(rootByte, &root)
		if err != nil {
			return nil, &model.HTTPError{Code: http.StatusNotFound, Err: err}
		}
		AddAllInFileCache("/", root)
		return &webdav.FileInfo{Path: "/", IsDir: true}, nil
	}
	tFile := GetFileFromFileCache(p)
	if tFile != nil {
		return tFile.ToFileInfo(), nil
	}
	return nil, fmt.Errorf("文件/文件夹不存在")
}

func (a AliFileSystem) Readdir(name string, recursive bool) ([]webdav.FileInfo, error) {

	p, err := a.localPath(name)
	if err != nil {
		return nil, err
	}
	file := GetFileFromFileCache(p)
	if file == nil {
		return nil, fmt.Errorf("文件/文件夹不存在")
	}
	if recursive {
		return nil, fmt.Errorf("暂不支持递归")
	}

	// 请求获取主文件夹
	rootReq := req.FileList{
		All:                   true,
		DriveId:               conf.AliConfSet.DriveId,
		ImageThumbnailProcess: "image/resize,w_400/format,jpeg",
		ImageUrlProcess:       "image/resize,w_1920/format,jpeg",
		Fields:                "*",
		VideoThumbnailProcess: "video/snapshot,t_0,f_jpg,ar_auto,w_300",
		ParentFileId:          file.FileId,
		UrlExpireSec:          1600,
	}
	rootByte, err := DoPost(FileList, rootReq)
	if err != nil {
		return nil, &model.HTTPError{Code: http.StatusNotFound, Err: err}
	}
	var root []*res.TFile
	err = json.Unmarshal(rootByte, &root)
	if err != nil {
		return nil, &model.HTTPError{Code: http.StatusNotFound, Err: err}
	}
	//缓存文件数据
	AddAllInFileCache(p, root)
	var folder []webdav.FileInfo
	for _, f := range root {
		folder = append(folder, *f.ToFileInfo())
	}
	return folder, err
}

func (a AliFileSystem) Create(name string) (io.WriteCloser, error) {
	panic("不支持")

}

func (a AliFileSystem) RemoveAll(name string) error {

	file := GetFileFromFileCache(name)
	if file != nil {
		rmReq := req.Remove{DriveId: conf.AliConfSet.DriveId, FileId: file.FileId}
		rmRes, err := DoPost(Remove, rmReq)
		if err != nil {
			return err
		}
		log2.Default().Println("rmRes", rmRes)

	}
}

func (a AliFileSystem) Mkdir(name string) error {
	panic("implement me")
}

func (a AliFileSystem) Copy(name, dest string, recursive, overwrite bool) (created bool, err error) {
	panic("implement me")
}

func (a AliFileSystem) MoveAll(name, dest string, overwrite bool) (created bool, err error) {
	panic("implement me")
}

func (a AliFileSystem) localPath(name string) (string, error) {
	if (filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0) || strings.Contains(name, "\x00") {
		return "", model.HTTPErrorf(http.StatusBadRequest, "webdav: invalid character in path")
	}
	name = path.Clean(name)
	if !path.IsAbs(name) {
		return "", model.HTTPErrorf(http.StatusBadRequest, "webdav: expected absolute path, got %q", name)
	}
	return filepath.Join(string(a), filepath.FromSlash(name)), nil
}

func (a AliFileSystem) externalPath(name string) (string, error) {
	rel, err := filepath.Rel(string(a), name)
	if err != nil {
		return "", err
	}
	return "/" + filepath.ToSlash(rel), nil
}
